/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools io
 */

#ifndef HMFS_IO_H
#define HMFS_IO_H

#include <memory>
#include "hmfs_command.h"

#ifndef HAVE_LSEEK64
typedef off_t off64_t;
#endif

namespace OHOS {
namespace Hmfs {
constexpr long RELOCATE_OFFSET_1 = 20;
constexpr long RELOCATE_OFFSET_2 = 40;
constexpr long RELOCATE_OFFSET_3 = 80;
constexpr long RELOCATE_OFFSET_4 = 160;
constexpr long RELOCATE_OFFSET_5 = 320;
constexpr long RELOCATE_OFFSET_6 = 640;
constexpr long RELOCATE_OFFSET_7 = 1280;
constexpr long RELOCATE_OFFSET_8 = 2560;
constexpr unsigned MAX_HASH_COLLISION = 16;

struct DevCacheConfig {
    long cacheEntryCount;
    unsigned maxCollisionCount;
    bool debugEnabled;
};

class Dcache {
public:
    static Dcache &GetInstance();
    static void DcacheInit();
    static void DcacheRelease();

    int32_t DcacheUpdateCache(int32_t fd, void *buf, off64_t offset, size_t count);
    int32_t DcacheRead(int32_t fd, void *buf, off64_t offset, size_t count);

private:
    Dcache() = default;

    inline char *DcacheAddr(long entry);
    inline long DcacheRelocate(long entry, int32_t index);
    long DcacheFind(off64_t block);
    int32_t DcacheIoRead(int32_t fd, long entry, off64_t offset, off64_t block);
    int32_t DcacheUpdateRw(int32_t fd, void *buf, off64_t offset, size_t byteCount, bool isWrite);
    int32_t DcacheUpdateRwPart(int32_t fd, long entry, off64_t start, off64_t block, bool isWrite);
    int32_t DcacheAllocAll(long num);
    void DcacheRelocateInit();

    static inline bool *dcacheValid_;        /* is the cached block valid? */
    static inline off64_t *dcacheBlk_;       /* which block it cached */
    static inline uint64_t *dcacheLastused_; /* last used ticks for cache entries */
    static inline char *dcacheBuf_;          /* cached block data */
    static inline uint64_t dcacheUsetick_;   /* current use tick */
    static inline uint64_t dcacheReadAccess_;
    static inline uint64_t dcacheReadHit_;
    static inline uint64_t dcacheReadMiss_;
    static inline uint64_t dcacheReadReplace_;
    static inline bool dcacheExitRegistered_ = false;
    static inline bool dcacheInitialized_ = false;

    static inline DevCacheConfig dcacheConfig_ = {0, MAX_HASH_COLLISION, 1};

    static inline long dcacheRelocateOffset0_[] = {
        RELOCATE_OFFSET_1, -RELOCATE_OFFSET_1,
        RELOCATE_OFFSET_2, -RELOCATE_OFFSET_2,
        RELOCATE_OFFSET_3, -RELOCATE_OFFSET_3,
        RELOCATE_OFFSET_4, -RELOCATE_OFFSET_4,
        RELOCATE_OFFSET_5, -RELOCATE_OFFSET_5,
        RELOCATE_OFFSET_6, -RELOCATE_OFFSET_6,
        RELOCATE_OFFSET_7, -RELOCATE_OFFSET_7,
        RELOCATE_OFFSET_8, -RELOCATE_OFFSET_8,
    };
    static inline int32_t dcacheRelocateOffset_[MAX_HASH_COLLISION];
};

class HmfsIo {
public:
    int32_t DevRead(void *buf, uint64_t offset, size_t len);
    int32_t DevReadAhead(uint64_t offset);
    int32_t DevWrite(void *buf, uint64_t offset, size_t len);
    int32_t DevWriteBlock(void *buf, uint64_t blockAddr);

    int32_t DevFill(void *buf, uint64_t offset, size_t len);
    int32_t DevFillBlock(void *buf, uint64_t blockAddr);
    int32_t DevReadBlock(void *buf, uint64_t blockAddr);
    int32_t DevReadaBlock(uint64_t blockAddr);

    int32_t HmfsFsyncDevice();
    int32_t HmfsFinalizeDevice();

    static HmfsIo &GetInstance();

private:
    HmfsIo() = default;
};
} // namespace Hmfs
} // namespace OHOS
#endif // HMFS_IO_H